﻿using Agile.Infra.Core.Agile.Extensions;
using Agile.Shared.WebApi.Authentication;
using Agile.Shared.WebApi.Authentication.Hybrid; 
using System.Security.Claims;

namespace Agile.Shared.WebApi.Registrar;

public abstract partial class AbstractWebApiDependencyRegistrar
{
    /// <summary>
    /// <summary>
    /// 注册身份认证组件
    /// </summary>
    protected virtual void AddAuthentication<TAuthenticationHandler>()
        where TAuthenticationHandler : AbstractAuthenticationProcessor
    {
        JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
        Services
            .AddScoped<AbstractAuthenticationProcessor, TAuthenticationHandler>();
        Services
            .AddAuthentication(HybridDefaults.AuthenticationScheme)
            .AddHybrid()
            .AddBasic(options => options.Events.OnTokenValidated = (context) =>
            {
                var userContext = context.HttpContext.RequestServices.GetService<UserContext>() ?? throw new NullReferenceException(nameof(UserContext));
                var principal = context.Principal ?? throw new NullReferenceException(nameof(context.Principal));

                SetUserContext(userContext, principal.Claims, context.HttpContext);

                return Task.CompletedTask;
            })
            .AddBearer(options => options.Events.OnTokenValidated = (context) =>
            {
                var userContext = context.HttpContext.RequestServices.GetService<UserContext>() ?? throw new NullReferenceException(nameof(UserContext));
                var principal = context.Principal ?? throw new NullReferenceException(nameof(context.Principal));

                SetUserContext(userContext, principal.Claims, context.HttpContext);

                return Task.CompletedTask;
            })
            //.AddJwtBearer(options =>
            //{
            //    var jwtConfig = Configuration.GetJWTSection().Get<JwtConfig>();
            //    options.TokenValidationParameters = JwtSecurityTokenHandlerExtension.GenarateTokenValidationParameters(jwtConfig);
            //    options.Events = JwtSecurityTokenHandlerExtension.GenarateJwtBearerEvents();
            //})
            ;
    }

    private void SetUserContext(UserContext userContext, IEnumerable<Claim> claims, HttpContext httpContext)
    {
        userContext.UserID = long.Parse(claims.First(x => x.Type == JwtRegisteredClaimNames.NameId).Value); 
        userContext.UserName = claims.First(x => x.Type == JwtRegisteredClaimNames.UniqueName).Value;
        userContext.ShowName = claims.First(x => x.Type == JwtRegisteredClaimNames.Name).Value;
        userContext.RemoteIpAddress = httpContext.GetClientIp();
    }
}
